package com.zbb.exam_system.bean;

import com.alibaba.fastjson.JSON;
import com.zbb.exam_system.dto.UserDto;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;


/**
 * 这里将JWT操作封装成了一个SpringBean，在使用的地方直接@Autowired注入即可
 */
@Component
public class JwtOperation {

    /**
     * 配置文件中的盐值
     */
    @Value("${jwt.config.secret}")
    private String secret;

    /**
     * 配置文件中的超时时间，-1代表永久，否则单位是秒
     */
    @Value("${jwt.config.expire}")
    private Long expire;


    /**
     * 创建JWT 【这个方法仅仅用在简单的Web应用整合案例中】
     *
     * @param id      用户id
     * @param subject 用户名
     * @param roles   用户角色
     * @return 创建的JWT的值
     */
    public String createJwt(String id, String subject, String... roles) {
        JwtBuilder jwtBuilder = Jwts.builder();
        jwtBuilder.setId(id);
        jwtBuilder.setSubject(subject);
        jwtBuilder.setIssuedAt(new Date());
        if (null != expire && !expire.equals(-1L)) {
            jwtBuilder.setExpiration(new Date(System.currentTimeMillis() + expire));
        }
        jwtBuilder.signWith(SignatureAlgorithm.HS256, secret);
        jwtBuilder.claim("roles", roles);
        return jwtBuilder.compact();
    }

    /**
     * 创建JWT 【这个方法用于SpringSecurity与JWT整合的案例中】
     *
     * @param user 使用数据库中合法的用户对象的相关信息来创建JWT
     * @return 创建的JWT的值
     */
    public String createJwt(UserDto user) {
        JwtBuilder jwtBuilder = Jwts.builder();
        jwtBuilder.setId(user.getUserId());
        jwtBuilder.setSubject(user.getUserName());
        jwtBuilder.setIssuedAt(new Date());
        if (null != expire && !expire.equals(-1L)) {
            jwtBuilder.setExpiration(new Date(System.currentTimeMillis() + expire));
        }
        jwtBuilder.signWith(SignatureAlgorithm.HS256, secret);
        //将得到的用户对象放入声明中，这里不能写实体类对象，那就写成JSON字符串
        jwtBuilder.claim("user", JSON.toJSONString(user));
        return jwtBuilder.compact();
    }


    /**
     * 解析JWT
     *
     * @param jwt 要解析的JWT
     * @return 解析后的结果
     */
    public Claims parseJwt(String jwt) {
        JwtParser jwtParser = Jwts.parser();
        return jwtParser.setSigningKey(secret).parseClaimsJws(jwt).getBody();
    }
}
